[GWCTF 2019]babyvm

简单vm题,甚至可以直接对着字节码写handle

提示是vm题

打开修复下符号,确实是vm题

进去修复下结构体,结构还是很明显的


修完后基本知道在干什么了,直接去看text段,指令有五百多个byte,写个脚本解析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
i = 0
f = open("output.txt", "w", encoding="utf-8")
cnt = 0
while i < len(text) and cnt < 2:
if text[i] == 0xF1:
print("mov ", end="", file=f)
op = text[i+1]
i += 2
num = text[i]+text[i+1]*256+text[i+2]*256*256+text[i+3]*256*256
if op == 0xE1:
print("r0 = input[{}]".format(num), file=f)
elif op == 0xE2:
print("r1 = input[{}]".format(num), file=f)
elif op == 0xE3:
print("r2 = input[{}]".format(num), file=f)
elif op == 0xE4:
print("input[{}] = r0".format(num), file=f)
elif op == 0xE5:
print("r3 = input[{}]".format(num), file=f)
elif op == 0xE7:
print("input[{}] = r1".format(num), file=f)
i += 4
elif text[i] == 0xF2:
print("r0 ^= r1", file=f)
i += 1
elif text[i] == 0xF5:
print("readInput", file=f)
i += 1
elif text[i] == 0xF4:
print("rip++", file=f)
i += 1
elif text[i] == 0xF7:
print("r0 *= r3", file=f)
i += 1
elif text[i] == 0xF8:
print("swap r0 r3", file=f)
i += 1
elif text[i] == 0xF6:
print("r0 = r2 + 2*r1 + 3*r0", file=f)
i += 1
elif text[i] == 0xF4:
i += 1
cnt += 1
# print(i, hex(text[i]))
f.close()

这题有个很恶心的地方,他text段有两段逻辑,并不是rip到0xF4就停止了,前一段是假flag,要用类似栈溢出的方法去第二段逻辑
最后手动逆出真正的加密逻辑如下

1
2
3
4
5
6
7
8
9
for i 1 ~ 5  input[i] ^= [i+1]

input[6]=(input[8]+2*input[7]+3*input[6])*input[12]
input[7]=(input[9]+2*input[8]+3*input[7])*input[12]
input[8]=(input[10]+2*input[9]+3*input[8])*input[12]
swap input[13] input[19]
swap input[14] input[18]
swap input[15] input[17]

直接逆即可
注意到密文也是假的,真正的密文在一个没有交叉引用的函数里

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
sec = [0x69, 0x45, 0x2A, 0x37, 0x09, 0x17, 0xC5, 0x0B, 0x5C, 0x72,
0x33, 0x76, 0x33, 0x21, 0x74, 0x31, 0x5F, 0x33, 0x73, 0x72]

for i in range(30, 127):
if sec[8] == ((sec[10]+2*sec[9]+3*i)*sec[12]) & 0xFF:
sec[8] = i
break
for i in range(30, 127):
if sec[7] == ((sec[9]+2*sec[8]+3*i)*sec[12]) & 0xFF:
sec[7] = i
break
for i in range(30, 127):
if sec[6] == ((sec[8]+2*sec[7]+3*i)*sec[12]) & 0xFF:
sec[6] = i
break
sec[15], sec[17] = sec[17], sec[15]
sec[14], sec[18] = sec[18], sec[14]
sec[13], sec[19] = sec[19], sec[13]
for i in range(5, -1, -1):
sec[i] ^= sec[i+1]
for i in sec:
print(hex(i), end=" ")
Author

SGSG

Posted on

2025-03-11

Updated on

2025-04-18

Licensed under